package ru.slovoslovo.cropmotion.cropping;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.slovoslovo.cropmotion.JAXBSerializer;

@XmlRootElement
public class CropTemplate extends JAXBSerializer{
    
    private static final Logger LOG = LoggerFactory.getLogger(CropTemplate.class);
    
    public static final String LOCATION = "./templates/";
    
    /**
     * Template title
     */
    private String title = "";
    
    /**
     * Template applying order
     * lower value is a higher priority
     */
    private int order = 100;
    
    /**
     * List of crop regions
     */
    private List<CropRegion> cropRegion = null;
    
    public CropTemplate(){
        super(CropTemplate.class);
    }

    public List<CropRegion> getCropRegion() {
        if (cropRegion == null){
            cropRegion = new ArrayList<CropRegion>();
        }
        return cropRegion;
    }

    public void setCropRegion(List<CropRegion> cropRegion) {
        this.cropRegion = cropRegion;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int applyOrder) {
        this.order = applyOrder;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    /**
     * Deserialize crop template from source file
     * 
     * @param source file path
     * @return deserialize template if success, null otherwise
     */
    public CropTemplate deserialize(String source) {
        CropTemplate result = null;
        
        try {
            result = (CropTemplate) getJaxbUnmarshaller().unmarshal(new FileInputStream(source));
        } catch (FileNotFoundException e) {
            LOG.error("Error deserializing crop template, source file not found, " + e.getMessage());
        } catch (JAXBException e) {
            LOG.error("Error deserializing crop template " + FilenameUtils.getBaseName(source) + ": " + (StringUtils.isNotEmpty(e.getMessage()) ? e.getMessage() : e.getLinkedException().getMessage()));
        }
        
        return result;
    }
    
    /**
     * Serialize crop template to destination file
     * 
     * @param template template
     * @param destiantion file path
     * @return operation result true/false
     */
    public boolean serialize(String destination) {
        boolean result = false;
        
        if (getJaxbMarshaller() != null){
            try {
                getJaxbMarshaller().marshal(this, new FileOutputStream(destination));
                result = true;
            } catch (FileNotFoundException e) {
                LOG.error("Error serializing crop template, destination file not found" + e.getMessage());
            } catch (JAXBException e) {
                LOG.error("Error serializing crop template" + e.getMessage());
            }
        }
        
        return result;
    }
    
    /**
     * Load all templates from specified folder and return its in list
     * 
     * @param source folder
     * @return loaded templates list
     */
    public static List<CropTemplate> loadTemplates(String folder) {
        List<CropTemplate> result = new ArrayList<CropTemplate>();
        
        File source = new File(folder);
        
        if (source.exists() && source.isDirectory()){
            for (File file : source.listFiles()){
                if (file.isFile() && "xml".equalsIgnoreCase(FilenameUtils.getExtension(file.getName()))){
                    CropTemplate template = new CropTemplate().deserialize(file.getAbsolutePath());
                    if (template != null){
                        result.add(template);
                        LOG.info("Template from " + file.getName() + " successfully loaded");
                    }                        
                }
            }
        }else{
            try {
                FileUtils.forceMkdir(source);
            } catch (IOException e) {
                LOG.error("Can't create templates " + LOCATION + "directory: ", e.getMessage());
            }
        }
        
        return result;
    }
    
    /**
     * Dynamic generate templates sample
     * 
     * @return generated templates list
     */
    public static List<CropTemplate> generateTemplates() {
        List<CropTemplate> templates = new ArrayList<CropTemplate>();

        CropTemplate template = new CropTemplate();
        
        template.setOrder(100);
        template.setTitle("Tempalte sample");
        template.getCropRegion().add(new CropRegion(25, 10, 10, AlignX.LEFT, AlignY.TOP));
        template.getCropRegion().add(new CropRegion(25, 10, 10, AlignX.RIGHT, AlignY.BOTTOM));
        template.getCropRegion().add(new CropRegion(50, 10, 0, AlignX.LEFT, AlignY.CENTER));
        template.getCropRegion().add(new CropRegion(50, 20, 0, AlignX.LEFT, AlignY.CENTER));
        template.getCropRegion().add(new CropRegion(50, 30, 0, AlignX.LEFT, AlignY.CENTER));
        template.getCropRegion().add(new CropRegion(50, 40, 0, AlignX.LEFT, AlignY.CENTER));
        template.getCropRegion().add(new CropRegion(50, 50, 0, AlignX.LEFT, AlignY.CENTER));
        template.getCropRegion().add(new CropRegion(75, 0, 0, AlignX.CENTER, AlignY.CENTER));
        template.getCropRegion().add(new CropRegion(100, 0, 0, AlignX.CENTER, AlignY.CENTER));
        templates.add(template);

        for (CropTemplate currentTemplate : templates){
            currentTemplate.serialize("D://template.xml");
        }
        
        return templates;
    }
    
}

